﻿using MRSite.Cache;
using MRSite.Cache.Configuration;
using MRSite.DataAccess.Config;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;

namespace MRSite.DataAccess
{
    public static class DbContextFactory
    {
        public static T Create<T>(ICacheManager cacheManager, string dbName, ICacheConfiguration cacheConfiguration)
        {
            try
            {
                var dbList = GetDatabaseList(cacheManager, cacheConfiguration);
                DatabaseInstance db = dbList.Find(x => x.Name == dbName);
                if (db != null && !string.IsNullOrWhiteSpace(db.ConnectionString))
                {
                    return (T)Activator.CreateInstance(typeof(T), db.ConnectionString);
                }
                return (T)Activator.CreateInstance(typeof(T));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        private static List<DatabaseInstance> GetDatabaseList(ICacheManager cacheManager, ICacheConfiguration cacheConfiguration)
        {
            if (ConfigHelper.DatabaseListFilePath == null || ConfigHelper.DatabaseListFilePath.Trim().Length <= 0
                    || File.Exists(ConfigHelper.DatabaseListFilePath.Trim()) == false)
            {
                return null;
            }
            cacheConfiguration.ConfigureOneCache(typeof(DbContextFactory).FullName, c =>
            {
                c.ChangeMonitors.Add(new HostFileChangeMonitor(new string[] { ConfigHelper.DatabaseListFilePath.Trim() }));
            });
            return cacheManager.GetCache(typeof(DbContextFactory).FullName).Get("GetDatabaseList",
                () =>
                {
                    var list = ConfigHelper.LoadDatabaseListFile();
                    if (list != null && list.DatabaseInstances != null && list.DatabaseInstances.Length > 0)
                    {
                        List<DatabaseInstance> rst = new List<DatabaseInstance>(list.DatabaseInstances.Length);
                        foreach (var db in list.DatabaseInstances)
                        {
                            if (db != null && string.IsNullOrWhiteSpace(db.Name) == false
                                && string.IsNullOrWhiteSpace(db.ConnectionString) == false)
                            {
                                if (rst.Exists(x => x.Name == db.Name.Trim()))
                                {
                                    throw new ApplicationException("Duplidated database name '" + db.Name + "' in configuration file '" + ConfigHelper.DatabaseListFilePath + "'.");
                                }
                                rst.Add(new DatabaseInstance()
                                {
                                    Name = db.Name.Trim(),
                                    ConnectionString = db.ConnectionString,//Decrypt(db.ConnectionString),
                                    Type = db.Type
                                });
                            }
                        }
                        return rst;
                    }
                    return null;
                });
        }
    }
}
